/*
	Alan Fortes
	CPE 301
	DA 5, part 1

	The following C program uses an ATMega328p to
	control the speed of a DC motor. This is done 
	by using a voltage divider, with the resistor 
	near ground being a potentiometer, to produce 
	a varying voltage from the middle of the voltage 
	divider. This voltage is then fed into the PC0(ADC0) 
	pin, and converted into a value using ADC conversion. 
	The values taken from the ADC register are then placed 
	into an equation to	find the appropriate value to place 
	in the OCR1A register, to produce a changing duty cycle
	that will determine the speed of the motor.
*/

#define F_CPU 8000000UL
#include <avr/io.h>
#include <stdio.h>
#include <avr/interrupt.h>
#include <util/delay.h>

int main(void)
{
	int ocrValue; //This variable stores integer value that will be placed into the OCR registers.
	double adcValue; //This variable stores the double value that is calculated from the ADC value that will be cast to the OCRvalue variable.
	
	DDRB = 0xFF; //The B port is set to be output output.	 	
	TCCR1B = 0x0D; //TCCR1B is set to be 13 so that CTC mode with a prescaler of 1024.
	ADCSRA = 0x82; //The ADC conversion is enabled with an appropriate sampling rate.
	 	
	while(1){
		
		ADCSRA |= (1<<ADSC); //this ADC conversion is enabled and set to begin.
		while((ADCSRA&(1<<ADIF))==0){
			
			
		}

		OCR1A = 1000; //The speed is determined by a duty cycle with a fixed off section 
					  //of OCR1A being 1000. The speed is changed by increasing or decreasing 
					  //the up
		while((TIFR1 & (1<<OCF1A)) == 0){
		}
		
		TIFR1 |= (1 << OCF1A);
		
		PORTB ^= 1;
		
		if(ADC < 70){
		
			adcValue = 250; //These values determine the speed by changing the amount of time
			                //the portion of the on duty cycle is up.
		}else if(ADC > 500){
		
			adcValue = 1884;
		
		}else{
			
			adcValue = ((ADC - 70) * 3.8) + 250; //If the motors has not reached the end points, an intermediary speed is found.
		}
		
		ocrValue = adcValue; //The calculated decimal value is cast to an int and sent to the OCR1A register.
		
		OCR1A = ocrValue;
		
		while((TIFR1 & (1<<OCF1A)) == 0){
		}
		
		TIFR1 |= (1 << OCF1A);
		PORTB ^= 1;		
	}
}




